package map.core.util;

import org.geotools.api.filter.FilterFactory;
import org.geotools.api.style.*;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.styling.*;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RasterStyleHelper {

    static StyleFactory sf = CommonFactoryFinder.getStyleFactory();
    static FilterFactory ff = CommonFactoryFinder.getFilterFactory();


    static List<String> codes = new ArrayList<>();
    static Map<String, Color[]> colorRamps = new HashMap<>();


    static {

        //红黄绿
        createColorRamp("5", 0Xff0000, 0Xffff00, 0X008000);
        //绿黄红
        createColorRamp("6", 0X008000, 0Xffff00, 0XFF0000);

        createColorRamp("4", 0Xffffe5, 0Xf7fcb9, 0Xd9f0a3, 0Xaddd8e, 0X78c679, 0X41ab5d, 0X238443);
        createColorRamp("1", 0Xd7191c, 0Xfdae61, 0Xffffbf, 0Xabdda4);
        createColorRamp("2", 0Xfafafa, 0X050505);
        createColorRamp("3", 0Xfef0d9, 0Xfdcc8a, 0Xfc8d59, 0Xe34a33, 0Xb30000);
        createColorRamp("7", 0Xffffcc, 0Xa1dab4, 0X41b6c4, 0X2c7fb8, 0X253494);
        createColorRamp("8", 0Xffffcc, 0Xc2e699, 0X78c679, 0X31a354, 0X006837);
        createColorRamp("9", 0X050505, 0Xffffcc, 0Xa1dab4, 0X41b6c4, 0X2c7fb8, 0X253494, 0X081d58);


        createColorRamp("test",  0X008000,0Xffff00,0Xff0000);

    }

    private static void createColorRamp(String code, int... colors) {
        Color[] colorArr = new Color[colors.length];
        for (int i = 0; i < colors.length; i++) {
            colorArr[i] = new Color(colors[i], false);
        }
        colorRamps.put(code, colorArr);
        codes.add(code);



    }


    public static Style createStyle(){
        RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
        ColorMap colorMap = sf.createColorMap();
        sym.setColorMap(colorMap);

         colorMap.addColorMapEntry(createColorMapEntry(0.000+0.00001, 0, Color.WHITE, "<0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.000+0.00002, 1.0, new Color(0X00cc00), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.001, 1.0, new Color(0X4fdc14), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.002, 1.0, new Color(0Xbbf22f), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.003, 1.0, new Color(0Xfcf03f), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.004, 1.0, new Color(0Xfbc83e), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.005, 1.0, new Color(0Xf9963c), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.006, 1.0, new Color(0Xf5623b), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.007, 1.0, new Color(0Xf3383a), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.008, 1.0, new Color(0Xf22751), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(0.009, 1.0, new Color(0Xf34085), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(99, 0, new Color(0Xf459b9), "0.000"));
        colorMap.addColorMapEntry(createColorMapEntry(99+Float.MAX_VALUE, 0, Color.WHITE, ">=99"));



        return SLD.wrapSymbolizers(sym);
    }

    /**
     * @param code
     * @param minValue
     * @param maxValue
     * @param clipMinValue
     * @param clipMaxValue
     * @return
     */
    public static Style createStyle(String code, double minValue, double maxValue, double clipMinValue, double clipMaxValue) {
        checkStyleCode(code);


        RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
         ColorMap colorMap = sf.createColorMap();


        Color[] colors = getColors(code);

        double step = (maxValue - minValue) / (colors.length - 1);


        colorMap.addColorMapEntry(createColorMapEntry(clipMinValue - 0.000001, 0, Color.WHITE, "noDataValue"));

        if(clipMinValue < minValue){
            colorMap.addColorMapEntry(createColorMapEntry(clipMinValue, 1, colors[0], String.valueOf(minValue)));

        }

        for (int i = 0; i < colors.length; i++) {
            double value = minValue + (step) * i;
            colorMap.addColorMapEntry(createColorMapEntry(value, 1, colors[i], String.valueOf(value)));
        }

        if(clipMaxValue > maxValue){
            colorMap.addColorMapEntry(createColorMapEntry(clipMaxValue, 1, colors[colors.length-1], String.valueOf(clipMaxValue)));

        }

        colorMap.addColorMapEntry(createColorMapEntry(clipMaxValue + 0.000001, 0, Color.WHITE, "noDataValue"));

        sym.setColorMap(colorMap);

        return SLD.wrapSymbolizers(sym);
    }

    private static  RasterSymbolizer createEmptyData(){
        RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
        ColorMap colorMap = sf.createColorMap();
        colorMap.addColorMapEntry(createColorMapEntry(-9999, 0, Color.WHITE, "noDataValue"));
        colorMap.addColorMapEntry(createColorMapEntry(9999, 0, Color.WHITE, "noDataValue"));
        sym.setColorMap(colorMap);

        return sym;
    }


    private static ColorMapEntry createColorMapEntry(double quantity, double opacity, Color color, String label) {
        ColorMapEntry entry = sf.createColorMapEntry();
        entry.setOpacity(ff.literal(opacity));
        entry.setQuantity(ff.literal(quantity));
        entry.setColor(ff.literal(color));
        entry.setLabel(label);
        return entry;
    }


    public static List<String> listStyleCode() {
        return codes;
    }

    public static List<Map<String, Object>> listStyle() {
        List<Map<String, Object>> list = new ArrayList<>();
        colorRamps.forEach((k, v) -> {
            Map<String, Object> map = new HashMap<>();
            map.put("code", k);
            map.put("colors", v);
            list.add(map);
        });

        return list;
    }

    static Color[] getColors(String code) {
        return colorRamps.get(code);
    }

    static void checkStyleCode(String code) {
        if (!colorRamps.containsKey(code)) {
            throw new RuntimeException("无效raster style code " + code);
        }
    }

}
